module ecs {
    export class NumberDeque {
        private _elements: number[];
        private _beginIndex: number;
        private _size: number = 0;

        constructor(capacity: number = 64){
            this._elements = new Array<number>(capacity);
        }

        public contains(e: number): boolean{
            for (let i = 0; this._size > i; i++){
                if (e == this._elements[this.index(i)])
                    return true;
            }

            return false;
        }

        public get(index: number){
            return this._elements[this.index(index)];
        }

        public size(): number{
            return this._size;
        }

        public getCapacity(){
            return this._elements.length;
        }

        public isEmpty(): boolean {
            return this._size == 0;
        }

        public add(e: number){
            if (this._size == this._elements.length)
                this.grow((this._elements.length * 7) / 4 + 1);

            this._elements[this.index(this._size ++)] = e;
        }

        public set(index: number, e: number){
            if (index >= this._elements.length){
                this.grow((index * 7) / 4 + 1);
            }
            this._size = Math.max(this._size, index + 1);
            this._elements[this.index(index)] = e;
        }

        public ensureCapacity(index: number){
            if (index >= this._elements.length)
                this.grow(index);
        }

        public popFirst(): number{
            this.assertNotEmpty();

            let value = this._elements[this._beginIndex];
            this._beginIndex = (this._beginIndex + 1) % this._elements.length;
            this._size --;
            return value;
        }

        private assertNotEmpty(){
            if (this._size == 0)
                throw new Error("Deque is empty");
        }

        private grow(newCapacity: number){
            let newElement = new Number[newCapacity];
            for (let i = 0; i < this._size; i ++)
                newElement[i] = this.get(i);

            this._elements = newElement;
            this._beginIndex = 0;
        }

        private index(relativeIndex): number{
            return (this._beginIndex + relativeIndex) % this._elements.length;
        }
    }
}